---
name: FAQ
route: /faq
---

import { Playground } from 'docz';
import { useMemo, useState } from 'react';

import ReactWordcloud from './react-wordcloud';
import words from './words';

# FAQ

## Re-rendering issues

Various props for `react-wordcloud` such as `size`, `callbacks`, `options` are array/object-based.  A common mistake in React components is to declare these conveniently as literal prop values:

```js
function MyWordcloud() {
  return (
    <ReactWordcloud
      options={{
        fontFamily: 'courier new',
        fontSizes: [10, 20],
      }}
      size={[400, 300]}
    />
  )
}
```

When your component re-renders, the array/object literal props are always initialized as new instances, and this causes the underlying `react-wordcloud` component to re-render as props have changed (React behavior).  To avoid this situation, either declare these prop values outside of your component, or memoize them:

```js
const size = [400, 300];
const options = {
  fontFamily: 'courier new',
  fontSizes: [10, 20],
};

function MyStaticWordcloud() {
  return (
    <ReactWordcloud
      options={options}
      size={size}
    />
  )
}
```

```js
import { useMemo } from 'react';

function MyMemoizedWordcloud() {
  const size = useMemo(() => {
    return [400, 300];
  }, []); // add dependencies to useMemo where appropriate

  const options = useMemo(() => {
    return {
      fontFamily: 'courier new',
      fontSizes: [10, 20],
    }
  }, []); // add dependencies to useMemo where appropriate

  return (
    <ReactWordcloud
      options={options}
      size={size}
    />
  );
}
```

Here is a playground that illustrates the difference between memoizing th;e `size` prop.

<Playground>
  {() => {
    const [iteration, setIteration] = useState(0);
    const size = [600, 300];  // this creates a new array when state updates
    const memoizedSize = useMemo(() => [600, 300], []);  // memoized. You can also simply just define the size variable itself outside of the componenet
    return (
      <div>
        <button onClick={() => setIteration(iteration + 1)}>
          Click to re-render
        </button>
        <h3>Will re-render because the 'size' prop is always recreated</h3>
        <ReactWordcloud size={size} words={words} />
        <h3>Will not re-render because the 'size' prop is memoized</h3>
        <ReactWordcloud size={memoizedSize} words={words} />
      </div>
    );
  }}
</Playground>

## Deterministic layouts
Please refer to the [Deterministic Behavior](../usage/options#deterministic-behaviour) section for more details on controlling deterministic layouts of wordclouds.

## Performance issues

### Cloud-based
Performance issues in the underlying `d3-cloud` layout can be encountered in these common situations:

- Multiple wordcloud instances.
- Large `words` data.
- High `maxWords` prop.
- Large `fontSizes` with small `size` prop (or parent container size).

The `options.enableOptimizations` flag can be uesd to solve the first two performance problems. For the other problems, you will have to experiment and pick ideal options to configure your wordclouds.

### Browser-based
`react-wordcloud` requires access to canvas data to render.  If browsers are blocking canvas data access (e.g. Firefox's `privacy.resistFingerprinting = true` which prompts for permission to access canvas data), you need to enable it.  If you are implementing projects that use `react-wordcloud`, you should inform users on how to get around the issue as shown in the example below:

```js
function MyWordcloud(props) {
  const canvasAllowed = typeof document !== 'undefined' && document.createElement('canvas').getContext('2d').getImageData(0, 0, 1, 1).data.every(v => v === 0);

  if (!canvasAllowed) {
    return (
      <p>
        React wordcloud requires access to canvas image data. Please allow
        access in your browser and reload the page.
      </p>
    );
  }

  return <ReactWordcloud {...props} />
```

## Dropped Words

This issue happens when the most _frequent_ word is also the _longest_ word. For a given wordcloud size, if the longest and most frequent word does not fit in the wordcloud SVG container, the `d3-cloud` algorithm drops them out. This is a known issue discussed in: [#36](https://github.com/jasondavies/d3-cloud/issues/36).

`react-wordcloud` tries to solve this issue by recursively rendering the wordcloud if it detects that words have been dropped out. Each recursion would decrease the applied font-size by a scale factor. The recursion will bail out after some maximum attempts is reached, and a console warning will be thrown to the user informing that the words cannot be rendered in the wordcloud. The following example below demonstrates this scenario.

<Playground>
  <ReactWordcloud
    size={[200, 200]}
    words={[
      { text: 'this_is_a_long_word_and_also_the_most_frequent', value: 60 },
      { text: 'some_word', value: 30 },
      { text: 'another_word', value: 20 },
    ]}
  />
</Playground>

If you see this console warning, it is recommended that you address it in the following ways:

- Increase the wordcloud size (either using the `size` prop or the parent container).
- Reduce the `options.fontSizes` values.
- Avoid rendering long words at vertical angles (i.e. 90 degrees). Browser heights are more limited than widths, and the long words may not fit within the wordcloud height. You can control rotation angles using `rotationAngles` and `rotations` in the `options` props.

## Typescript errors
Common typescript issues are frequently experienced when working with `Scale`, `Spiral`, `MinMaxPair` types where providing literal number arrays or strings will cause the TS compiler to complain.  Most of these are type aliases (e.g. `[number, number]` and `'linear' | 'log' | 'sqrt'`) and you can resolve these issues by type-asserting them e.g.

```ts
const fonSizes: MinMaxPair = [10, 20];
const fontSizes = [10, 20] as MinMaxPair;

const scale = 'linear' as const;
const scale = <const> 'linear';
```
